/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package application;

import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.tree.DefaultMutableTreeNode;
import jpcap.*;
import jpcap.packet.Packet;

/**
 *
 * @author lbl
 */
public class Captor {

    private boolean isLive;
    private JpcapCaptor jpcap;
    private NetworkInterface[] devices;
    private dataTable dt;
    private Thread captureThread;
    private int n;

    /**
     *
     */
    public Captor() {
        isLive = false;
        jpcap = null;
        captureThread = null;
        n = 0;
    }

    /**
     *
     * @return
     */
    public String[] getDeviceName() {
        devices = JpcapCaptor.getDeviceList();
        String[] s = new String[devices.length];
        for (int i = 0; i < devices.length; i++) {
            s[i] = devices[i].description;
        }
        return s;
    }

    /**
     *
     */
    public void createTable() {
        dt = new dataTable();
    }

    /**
     *
     * @return
     */
    public dataTable getTable() {
        return this.dt;
    }

    /**
     *
     */
    public void clearTable() {
        n = 0;
        this.dt.clear();
    }

    /**
     *
     * @param num
     */
    public void captureFromDevice(int num) {
        if (jpcap != null) {
            jpcap.close();
        }
        try {
            jpcap = JpcapCaptor.openDevice(devices[num], 65535, false, 20);
        } catch (IOException ex) {
            Logger.getLogger(Captor.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.out.println("init captor");
        if (jpcap != null) {
            isLive = true;
            startCapture();
        }
    }

    /**
     *
     */
    public void startCapture() {
        if (captureThread != null) {
            return;
        }
        System.out.println("start captor");
        captureThread = new Thread(new Runnable() {
            //body of capture thread

            public void run() {
                while (captureThread != null) {
                    if (jpcap.processPacket(1, handler) == 0 && !isLive) {
                        stopCapture();
                    }
                    Thread.yield();
                }
            }
        });

        captureThread.setPriority(
                Thread.MIN_PRIORITY);
        captureThread.start();
    }

    /**
     *
     */
    public void stopCapture() {
        captureThread = null;
    }
    private PacketReceiver handler = new PacketReceiver() {

        public void receivePacket(final Packet packet) {
            dt.addPacket(packet, ++n);
        }
    };

    /**
     *
     * @param num
     * @return
     */
    public String getHexPacketData(int num) {
        StringBuffer sb = new StringBuffer(dt.getHexPacket(num));
        for (int i = 0; i < sb.length(); i += 1) {
            if (i % 48 == 47) {
                sb.insert(i, "\n");
            } else if (i % 3 == 2) {
                sb.insert(i, " ");
            }
        }
        return sb.toString();
    }

    /**
     *
     * @param num
     * @return
     */
    public String getASCIIPacketData(int num) {
        StringBuffer sb = new StringBuffer(dt.getASCIIPacket(num));
        for (int i = 0; i < sb.length(); i += 1) {
            if (i % 16 == 15) {
                sb.insert(i, "\n");
            }
        }
        return sb.toString();
    }

    /**
     *
     * @param num
     * @return
     */
    public DefaultMutableTreeNode getRoot(int num) {
        return dt.getRootNode(num);
    }

    /**
     *
     * @param file
     */
    public void loadPacketsFromFile(String file) {
        try {
            if (jpcap != null) {
                jpcap.close();
            }
            jpcap = JpcapCaptor.openFile(file);
        } catch (IOException e) {
            JOptionPane.showMessageDialog(
                    null, "Can't open file: " + file, "Error",
                    JOptionPane.ERROR_MESSAGE);
            e.printStackTrace();
            return;
        }
        startCapture();
    }

    /**
     *
     * @param file
     */
    public void savePacketsToFile(String file) {
        File f = new File(file);
        if (f.exists()) {
            if (JOptionPane.showConfirmDialog(
                    null,
                    "Overwrite " + f.getName() + "?",
                    "Overwrite?",
                    JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
                return;
            }
        }
        try {
            JpcapWriter writer = JpcapWriter.openDumpFile(jpcap, f.getPath());
            Packet[] packets = dt.getAllPackets();
            for (Packet p : packets) {
                writer.writePacket(p);
            }

            writer.close();
        } catch (java.io.IOException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(
                    null,
                    "Can't save file: " + f.getPath());
        }
    }

    /**
     *
     * @param p
     */
    public void setFilterProtocol(String p) {
        dt.setProtocol(p);
    }

    /**
     *
     * @param s
     */
    public void setFilterSource(String s) {
        dt.setSource(s);
    }

    /**
     *
     * @param d
     */
    public void setFilterDestination(String d) {
        dt.setDestination(d);
    }

    /**
     *
     * @param q
     */
    public void setFilterQuery(String q) {
        dt.setQuery(q);
    }

    /**
     *
     * @param b
     */
    public void setMatchCase(Boolean b) {
        dt.setMatchCase(b);
    }

    /**
     *
     */
    public void filterChanged() {
        dt.fireFilterChanged();
    }

    /**
     *
     * @param file
     * @param num
     */
    public void savePacket(String file, int num) {
        try {
            dt.savePacket(file, num);
        } catch (java.io.IOException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(
                    null,
                    "Can't save file: " + file);
        }
    }

    /**
     *
     * @param file
     * @param num
     */
    public void reassemblePacket(String file, int num) {
        try {
            dt.reassemblePacket(file, num);
        } catch (java.io.IOException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(
                    null,
                    "Can't save file: " + file);
        }
    }
}
